//
// Created by lenovo on 2024/6/28.
//

#ifndef TEYVATSURVIVAL_GRAPHIC_GRAPHIC_H
#define TEYVATSURVIVAL_GRAPHIC_GRAPHIC_H

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <string>
#include <utility>
#include <vector>
#include "../utils/Vector.h"

namespace Game::Graphic{
    using Vector2f = sf::Vector2f;

    using string = std::string ;

    extern std::string IMG_RESOURCE;
    extern string BACKGROUND_PIC_SIZE ;

    class AnimationBase {
    public:
        // 图片相关
        std::vector<string> paths;
        Vector2f position;
        Vector2f scale;
        float opacity;
        // 播放相关
        int idx ;
        float interval;
        bool loop;
        enum class State { Playing, Paused, Stopped };
        State state;

        // 构造函数
        AnimationBase() :
                state(State::Stopped) , loop(false) , opacity(1) , idx(0) , interval(0.3f)
        {};

        AnimationBase(const std::vector<string>& paths, const Vector2f& position, int interval, bool loop , float opacity)
                : paths(paths), position(position), opacity(opacity), interval(interval), loop(loop), state(State::Stopped) , idx(0) {}

        // Getter 方法
        std::vector<string> getPaths() const { return paths; }
        Vector2f getPosition() const { return position; }
        float getOpacity() const { return opacity; }
        float getInterval() const { return interval; }
        bool isLoop() const { return loop; }
        State getState() const { return state; }
        int getIdx() const {return idx ;}
        Vector2f getSize() const {return scale;}

        // Setter 方法
        void setIdx (int i) {idx = i ;}
        void setPaths(const std::vector<string>& newPaths) { paths = newPaths; }
        void addPath(string p){paths.push_back(p);}
        void setPosition(const Vector2f& newPosition) { position = newPosition; }
        void setOpacity(float newOpacity) { opacity = newOpacity; }
        void setInterval(float newInterval) { interval = newInterval; }
        void setLoop(bool newLoop) { loop = newLoop; }
        void setState(State newState) { state = newState; }
        void setSize(const Vector2f& newSize) { scale = newSize;}
    };


    // Animation 类定义
    class Animation : public sf::Drawable{
    public:
        Animation(const AnimationBase& animation)
                : base(animation), currentFrame(0), elapsedTime(0) {
            loadTextures();
        }

        Animation() = default;

        void update(float deltaTime) {
            if (base.state == AnimationBase::State::Playing) {
                elapsedTime += deltaTime;
                if (elapsedTime >= base.interval) {
                    elapsedTime = 0;
                    currentFrame++;
                    if (currentFrame >= textures.size()) {
                        if (base.loop) {
                            currentFrame = 0;
                        } else {
                            currentFrame = textures.size() - 1;
                            base.state = AnimationBase::State::Stopped;
                        }
                    }
                }
            }
        }

        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override {
            if (!textures.empty() && base.state != AnimationBase::State::Stopped) {
                sf::Sprite sprite;
                sprite.setTexture(textures[currentFrame]);
                sprite.setPosition(
                        sf::Vector2f(base.position.x, base.position.y)
                );
                sprite.setColor(sf::Color(255, 255, 255, static_cast<sf::Uint8>(base.opacity * 255)));

                // Calculate scale factors based on desired scale and texture scale
                if (scaled)
                if (base.scale.x > 0 && base.scale.y > 0) {
                    sf::Vector2u textureSize = textures[currentFrame].getSize();
                    sprite.setScale(
                            base.scale.x / textureSize.x,
                            base.scale.y / textureSize.y
                    );
                }

                target.draw(sprite, states);
            }
        }

        // Getter 和 Setter 代理方法
        std::vector<string> getPaths() const { return base.getPaths(); }
        Vector2f getPosition() const { return base.getPosition(); }
        float getOpacity() const { return base.getOpacity(); }
        float getInterval() const { return base.getInterval(); }
        bool isLoop() const { return base.isLoop(); }
        AnimationBase::State getState() const { return base.getState(); }
        int getIdx() const { return base.getIdx(); }
        Vector2f getScale() const {return base.scale;}

        void setIdx(int i) { base.setIdx(i); }
        void setPaths(const std::vector<string>& newPaths) { base.setPaths(newPaths); }
        void addPath(string p) { base.addPath(p); }
        void setPosition(const Vector2f& newPosition) { base.setPosition(newPosition); }
        void setOpacity(float newOpacity) { base.setOpacity(newOpacity); }
        void setInterval(float newInterval) { base.setInterval(newInterval); }
        void setLoop(bool newLoop) { base.setLoop(newLoop); }
        void setState(AnimationBase::State newState) { base.setState(newState); }
        void setScale(const Vector2f& s) {
            scaled = true ;
            base.scale = s;
        }
        void rescale () {
            scaled = false ;
        };
        void play() {base.setState(AnimationBase::State::Playing);}
        void pause() {base.setState(AnimationBase::State::Paused);}
        void stop() {base.setState(AnimationBase::State::Stopped);}


    public:
        void loadTextures() {
            for (const auto& path : base.paths) {
                sf::Texture texture;
                if (texture.loadFromFile(path)) {
                    textures.push_back(texture);
                }
            }
        }

        AnimationBase base;
        bool scaled = false;
        std::vector<sf::Texture> textures;
        size_t currentFrame;
        float elapsedTime;
    };

    class iAnimaBuilder {
    public:
        using Builder = iAnimaBuilder;

        virtual Builder& addPath(const std::string& path) = 0;
        virtual Builder& opacity(float opacity) = 0;
        virtual Builder& interval(float interval) = 0;
        virtual Builder& idx(int idx) = 0;
        virtual Builder& loop(bool loop) = 0;
        virtual Builder& position (Vector2f pos) = 0 ;
        virtual Builder& play() = 0 ;
        virtual Builder& pause() = 0 ;
        virtual Builder& stop() = 0 ;
        virtual Builder& scale( Vector2f  s) = 0;
        virtual Animation* build() = 0;

        virtual ~iAnimaBuilder() {  };
    };


    // AnimationBuilder 类定义
    class AnimationBuilder : public iAnimaBuilder {
    public:
        using Builder = AnimationBuilder;

        Builder& addPath(const std::string& path) override {
            paths.push_back(path);
            return *this;
        }

        Builder& opacity(float opacity) override {
            this->_opacity = opacity;
            return *this;
        }

        Builder& interval(float interval) override {
            this->_interval = interval;
            return *this;
        }

        Builder& idx(int idx) override {
            this->_idx = idx;
            return *this;
        }

        Builder& loop(bool loop) override {
            this->_loop = loop;
            return *this;
        }

        Builder& position (Vector2f pos){
            this->_position = pos;
            return *this;
        }

        Builder& scale(Vector2f size) override{
            this->_scaled = true  ;
            this->_scale = size;

            return *this ;
        }

        Builder& play() override {
            this->status = 0 ;
            return *this ;
        }

        Builder& pause() override {
            this->status = 1 ;
            return *this ;
        }

        Builder& stop() override {
            this->status = 2 ;
            return *this ;
        }
        Animation* build() override {
            AnimationBase animationBase(paths, _position, _interval, _loop, _opacity);
            animationBase.setIdx(_idx);
            auto* anima = new Animation(animationBase);
            if (status == 0){
                anima->play();
            }
            else if (status == 1){
                anima->pause();
            }
            else if (status == 2){
                anima->stop();
            }

            if (_scaled)
                anima->setScale(_scale);

            return anima;
        }

    private:
        std::vector<std::string> paths;
        Vector2f _position;
        Vector2f _scale;
        bool _scaled ;
        float _opacity = 1.0f;
        float _interval = 0.3f;
        int _idx = 0;
        bool _loop = false;
        int status = 0 ;
    };


    class BackgroundRenderer : public sf::Drawable {
    public:
        explicit BackgroundRenderer(const std::string& imagePath) {
            // 加载背景纹理
            if (!texture.loadFromFile(imagePath)) {
                std::cerr << "Failed to load image" << std::endl;
            }

            // 获取纹理的原始尺寸
            textureSize = texture.getSize();

            // 设置背景精灵
            sprite.setTexture(texture);
        }

        // 函数用于调整背景精灵的大小和位置
        void resizeSprite(const sf::Vector2u& windowSize) {
            // 计算缩放比例
            float scaleX = static_cast<float>(windowSize.x) / textureSize.x;
            float scaleY = static_cast<float>(windowSize.y) / textureSize.y;

            // 选择较小的缩放比例以保持图像比例
            float scale = std::min(scaleX, scaleY);

            // 设置精灵的缩放比例
            sprite.setScale(scale, scale);

            // 使精灵居中
            sprite.setPosition(
                    (windowSize.x - textureSize.x * scale) / 2,
                    (windowSize.y - textureSize.y * scale) / 2
            );
        }

        // 处理窗口事件，例如窗口大小变化
        void handleEvent(const sf::Event& event, const sf::Vector2u& windowSize) {
            if (event.type == sf::Event::Resized) {
                resizeSprite(windowSize);
            }
        }

    public:
        // 重载 draw 方法
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override {
            target.draw(sprite, states);
        }

        sf::Texture texture;
        sf::Sprite sprite;
        sf::Vector2u textureSize;
    };

}
#endif //TEYVATSURVIVAL_GRAPHIC_GRAPHIC_H
